package com.sunl.mall.ali.mq.autoconfigure.util;

import com.sunl.mall.ali.mq.producer.RocketMqTransactionProducerBean;
import com.sunl.mall.common.util.SpringBootPropertyUtil;
import com.sunl.mall.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedProperties;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.env.Environment;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

public final class RegUtil {
    private static final Logger log = LoggerFactory.getLogger(RegUtil.class);

    private RegUtil() {
    }

    @SuppressWarnings("unchecked")
    public static <T> void registerRocketMqProducerBeans(BeanDefinitionRegistry registry, String producerPrefix, Class<T> mqProducerBanClass, Environment environment) {
        HashMap<String, LinkedHashMap<String, Object>> producers = null;
        try {
            producers = SpringBootPropertyUtil.getProperties(environment, producerPrefix, HashMap.class);
        } catch (Exception e) {
            log.error("创建mq producer 失败. err:[{}]", e.getMessage());
        }
        if (producers == null || producers.isEmpty()) {
            log.debug("No {} found.", mqProducerBanClass.getName());
            return;
        }
        for (String producerBeanName : producers.keySet()) {
            Map<String, Object> producerConfigMap = producers.get(producerBeanName);
            if (producerConfigMap == null || producerConfigMap.isEmpty()) {
                throw new IllegalArgumentException("MqProducer[" + producerPrefix + producerBeanName + "] properties must not empty!");
            }
            Properties properties = new ManagedProperties();
            String transactionMessageCheckerBeanName = null;
            for (String configName : producerConfigMap.keySet()) {
                // 事务消息生产者需要额外处理回查逻辑
                if (mqProducerBanClass == RocketMqTransactionProducerBean.class && "transactionMessageCheckerBeanName".equals(configName)) {
                    transactionMessageCheckerBeanName = (String) producerConfigMap.get(configName);
                    continue;
                }
                properties.setProperty(configName, (String) producerConfigMap.get(configName));
            }
            if (mqProducerBanClass == RocketMqTransactionProducerBean.class && StringUtil.isBlank(transactionMessageCheckerBeanName)) {
                throw new IllegalArgumentException("MqProducer[" + producerPrefix + producerBeanName + ".transactionMessageCheckerBeanName] properties must not empty!");
            }
            registerRocketMqProducerBeans(mqProducerBanClass, producerBeanName, registry, properties, transactionMessageCheckerBeanName);
        }
    }

    private static void registerRocketMqProducerBeans(Class<?> mqProducerBanClass, String beanName, BeanDefinitionRegistry registry, Properties properties, String transactionMessageCheckerBeanName) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(mqProducerBanClass);
        beanDefinition.getPropertyValues().addPropertyValue("properties", properties);
        if (StringUtil.isNotBlank(transactionMessageCheckerBeanName)) {
            beanDefinition.getPropertyValues().addPropertyValue("rocketMqTransactionMessageChecker", new RuntimeBeanReference(transactionMessageCheckerBeanName));
        }

        beanDefinition.setInitMethodName("start");
        beanDefinition.setDestroyMethodName("shutdown");
        registry.registerBeanDefinition(beanName, beanDefinition);
    }
}
